/*
STL map/multimap容器
map中所有的元素都是pair, 第一个元素为key, 起到索引作用，第二个元素为value, 所有元素都会根据key自动排序
map/multimap 与 set/multiset一样 都是属于关联式容器，底层是二叉树实现
map中不允许容器有重复的key，multimap中允许容器有重复的key

map 构造函数与赋值
  函数原型
    map<T1, T2> mp;  // 默认构造函数
    map(initializer_list<T1, T2> il);  // 列表初始化 不知道构造函数是不是这样 没到找列表初始化的构造函数 反正可以使用列表初始化去构造 >=c++ 11
    map(const map& mp);  // 拷贝构造函数
    map& operator=(const map& mp);  // 重载等号操作符

map 大小和交换
  与set用法相似
  函数原型
    empty();  // 判断容器是否为空
    size();  // 返回容器中元素的数目
    swap(mp);  // 交换两个容器

map 插入和删除
  函数原型
    insert(elem);  // 向容器中插入elem
    erase(pos);  // 删除pos迭代器所指位置的元素，返回下一个元素的迭代器
    erase(beg, end);  // 删除区间[beg, end)的所有元素，返回下一个元素的迭代器
    erase(key);  // 删除容器中值为key的元素

map 查找和统计
  函数原型
    find(key);  // 查找key是否存在，存在返回改元素的迭代器，不存在返回map.end();
    cout(key):  // 统计key元素的个数

map 排序
  利用仿函数修改默认排序(从小到大)规则
  注意 要写成常函数 不变编译会出错
*/

#include <iostream>
#include <map>
#include <string>
using namespace std;

template <typename T1, typename T2>
void print_mp(const map<T1, T2> &m)
{
    for (auto it = m.begin(); it != m.end(); it++)
        cout << "key: " << it->first << " value: " << it->second << endl;
}

// map 构造函数与赋值
void func1()
{
    cout << "---------------- constribute&assign -------------------" << endl;
    map<int, int> m1 = {{1, 1}, {2, 2}, {3, 3}}; // map(initializer_list<T1, T2> il);
    print_mp<int, int>(m1);

    map<string, int> m2; // map<T1, T2> mp;
    m2.insert(pair<string, int>("alex", 11));
    m2.insert(pair<string, int>("ieven", 15));
    m2.insert(pair<string, int>("jordan", 19));
    print_mp<string, int>(m2);

    map<int, int> m3(m1); // map& map(const map& mp);
    print_mp<int, int>(m3);

    map<string, int> m4;
    m4 = m2; // map& operator=(const map& mp);
    print_mp<string, int>(m4);
}

// map 大小和交换
void func2()
{
    cout << "---------------- size&swap -------------------" << endl;
    map<int, int> m1 = {{1, 1}, {2, 2}, {3, 3}}; // map(initializer_list<T1, T2> il);
    cout << "m1-> " << endl;
    print_mp<int, int>(m1);
    cout << "m1.empty: " << m1.empty() << " m1.size: " << m1.size() << endl;

    map<int, int> m2 = {{4, 4}, {3, 9}};
    cout << "m2-> " << endl;
    print_mp<int, int>(m2);

    cout << "== swap ==" << endl;
    m2.swap(m1);

    cout << "m1-> " << endl;
    print_mp<int, int>(m1);

    cout << "m2-> " << endl;
    print_mp<int, int>(m2);
}

// map 插入和删除
void func3()
{
    cout << "---------------- insert&erase -------------------" << endl;
    map<string, int> m2;
    m2.insert(pair<string, int>("alex", 11));
    m2.insert(pair<string, int>("ieven", 15));
    m2.insert(pair<string, int>("jordan", 19));
    print_mp<string, int>(m2);

    m2.erase(m2.begin());
    cout << "m2.erase(m2.begin()) -> " << endl;
    print_mp<string, int>(m2);

    m2.erase("jordan");
    cout << "m2.erase(jordan) -> " << endl;
    print_mp<string, int>(m2);
}

// map 查找和统计
void func4()
{
    cout << "---------------- find&count -------------------" << endl;
    map<int, int> m1 = {{1, 1}, {2, 2}, {3, 3}}; // map(initializer_list<T1, T2> il);
    print_mp<int, int>(m1);

    map<int, int>::iterator it = m1.find(2);
    cout << "m1.find(2) -> " << it->first << ", " << it->second << endl;

    int c = m1.count(2);
    cout << "m1.count(2) -> " << c << endl;
}

// map 排序
class MyIntCompare
{
public:
    bool operator()(int n1, int n2) const
    {
        return n1 > n2;
    }
};

void func5()
{
    cout << "---------------- sort -------------------" << endl;
    map<int, int, MyIntCompare> m1 = {{1, 1}, {2, 2}, {3, 3}};
    // print_mp(m1);
    for (map<int, int, MyIntCompare>::iterator it = m1.begin(); it != m1.end(); it++)
        cout << it->first << ", " << it->second << endl;
}

int main()
{
    func1(); // map 构造函数与赋值
    func2(); // map 大小与交换
    func3(); // map 插入和删除
    func4(); // map 查找和统计
    func5(); // map 排序

    return 0;
}